home *** CD-ROM | disk | FTP | other *** search
- { The 5 date functions in this unit implement an amazingly efficient algorithm
- used in the Hewlett-Packard 12C calculator. Similar routines in commercial
- libraries are relatively huge and rely on brute force. Dates are stored as
- compact 4 byte LongInts giving the routines an effective range from the 1st
- day A.D. to December 31, 9999. (By then we will use another calander!)
-
- These routines in this unit are donated to the public domain by their author:
- John Roncalio, 34439 Ascott Avenue, Abbotsford, B.C., Canada. V2S 4V6
-
- More date routines are available in the BlueBag unit included with the
- ASG52.ARC file in this section. Also included are lots of routines for the
- CRT, cursors, Printer status testing, strings, windows and data entry. It
- really is worth taking a look at. }
-
- {$R-}
- UNIT Dates;
- INTERFACE
- TYPE
- Date = LONGINT;
- DateString = STRING[8]; {'MoDyYear' expected. eg: '07041776' = Independence}
- DofW = 1..7;
- CONST
- BadDate = $7FFFFFFF;
- DayName : ARRAY[1..7] OF STRING[9] =
- ('Saturday','Sunday','Monday','Tuesday','Wednesday','Thursday','Friday');
-
- FUNCTION DateStringToDate(DS:DateString):Date;
- FUNCTION DateToDateString(DT:Date):DateString;
- FUNCTION DayOfWeek(DT:Date):DofW;
- FUNCTION SysDate:Date;
- FUNCTION ValidDate(DS:DateString):BOOLEAN;
-
- IMPLEMENTATION
- USES Dos;
- CONST
- DaysInYr :REAL=365.25;
- VAR
- Done,
- LeapYear :BOOLEAN;
- Er :INTEGER;
- Y,M,D,Z :LONGINT;
-
- FUNCTION DateStringToDate;
- BEGIN
- IF NOT ValidDate(DS) THEN DateStringToDate:=BadDate ELSE
- BEGIN
- IF M<=2 THEN Z:=Trunc((Y-1)/4) ELSE Z:=Trunc(Y/4) - Trunc(0.4*M+2.3);
- DateStringToDate:=365*Y+31*(M-1)+D+Z;
- END;
- END;
-
- FUNCTION DateToDateString;
- VAR Ys : STRING[4];
- Ms,Ds : STRING[2];
- TempDate : STRING[8];
- BEGIN
- Y:=Trunc(DT/DaysInYr); STR(Y:4,Ys); M:=0;
- D:=Trunc((DT/DaysInYr-Y)*DaysInYr+0.00001);
- LeapYear := (Y/4 = Y DIV 4); Done:=False;
- REPEAT
- INC(M);
- CASE M OF
- 1,3,5,7,8,10,12 : IF D>31 THEN DEC(D,31) ELSE Done:=True;
- 2: IF LeapYear THEN IF D>28 THEN DEC(D,29) ELSE Done:=True
- ELSE IF D>27 THEN DEC(D,28) ELSE Done:=True;
- ELSE IF D>30 THEN DEC(D,30) ELSE Done:=True;
- END; {case}
- UNTIL Done;
- STR(M:2,Ms); STR(D+1:2,Ds); TempDate:=Ms+Ds+Ys;
- FOR D:=1 TO 6 DO IF TempDate[D]=#32 THEN TempDate[D]:='0';
- DateToDateString:=TempDate;
- END;
-
- FUNCTION DayOfWeek;
- VAR Dctr : BYTE;
- TmpDt : Date;
- BEGIN
- TmpDt:=Dt; Done:=False; Dctr:=0;
- REPEAT
- IF TmpDt/7 = TmpDt DIV 7 THEN Done:=True ELSE
- BEGIN
- INC(Dctr); INC(TmpDt);
- END;
- UNTIL Done;
- DayOfWeek:=7-Dctr;
- END;
-
- FUNCTION SysDate;
- VAR A,B,C,D : WORD;
- BEGIN
- GetDate(A,B,C,D); Y:=A; M:=B; D:=C;
- IF M<=2 THEN Z:=Trunc((Y-1)/4) ELSE Z:=Trunc(Y/4) - Trunc(0.4*M+2.3);
- SysDate:=365*Y+31*(M-1)+D+Z;
- END;
-
- FUNCTION ValidDate;
- BEGIN
- ValidDate:=False;
- IF DS[0]<>#8 THEN EXIT;
- VAL(COPY(DS,5,4),Y,Er); IF (Er<>0) OR (Y<0) THEN EXIT;
- VAL(COPY(DS,1,2),M,Er); IF (Er<>0) OR (NOT M IN [1..12]) THEN EXIT;
- VAL(COPY(DS,3,2),D,Er); IF (Er<>0) OR (D<1) THEN EXIT;
- LeapYear := (Y/4 = Y DIV 4);
- CASE M OF
- 1,3,5,7,8,10,12:IF D<=31 THEN ValidDate:=True;
- 2:IF LeapYear THEN
- BEGIN
- IF D<=29 THEN ValidDate:=True;
- END ELSE IF D<=28 THEN ValidDate:=True;
- ELSE IF D<=30 THEN ValidDate:=True;
- END; {case}
- END;
-
- END.